dependent_var <- "MEDHVAL"

predictors <- c("PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")

summary_stats <- data %>%
  select(all_of(c(dependent_var, predictors))) %>%
  summarise_all(list(Mean = mean, SD = sd), na.rm = TRUE) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
  separate(Variable, into = c("Variable", "Stat"), sep = "_") %>%
  pivot_wider(names_from = Stat, values_from = Value)



summary_stats$Variable <- recode(summary_stats$Variable,
  "MEDHVAL" = "Median House Value",
  "NBELPOV100" = "# Households Living in Poverty",
  "PCTBACHMOR" = "% of Individuals with Bachelor’s Degrees or Higher",
  "PCTVACANT" = "% of Vacant Houses",
  "PCTSINGLES" = "% of Single House Units"
)



summary_stats <- summary_stats %>%
  mutate(
    Mean = round(Mean, 2),
    SD = round(SD, 2)
  )

summary_stats <- summary_stats %>%
  arrange(Variable == "Median House Value")

predictor_rows <- which(summary_stats$Variable != "Median House Value")
dependent_rows <- which(summary_stats$Variable == "Median House Value")

# Determine the start and end rows for each group
start_pred <- min(predictor_rows)
end_pred   <- max(predictor_rows)
start_dep  <- min(dependent_rows)
end_dep    <- max(dependent_rows)

# Create the table using kable and add extra formatting
kable(summary_stats, caption = "Summary Statistics", 
      align = c("l", "l", "l"), booktabs = TRUE, escape = FALSE ) %>%
  add_header_above(c(" " = 1, "Statistics" = 2)) %>%
  kable_styling(full_width = FALSE) %>%
  group_rows("Predictors", start_pred, end_pred) %>%
  group_rows("Dependent Variable", start_dep, end_dep)%>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE)
Summary Statistics
Statistics
Variable Mean SD
Predictors
% of Individuals with Bachelor’s Degrees or Higher 16.08 17.77
# Households Living in Poverty 189.77 164.32
% of Vacant Houses 11.29 9.63
% of Single House Units 9.23 13.25
Dependent Variable
Median House Value 66287.73 60006.08
#check 0
columns_to_check <- c(dependent_var, predictors)

zero_counts <- sapply(data[columns_to_check], function(x) sum(x == 0, na.rm = TRUE))

zero_counts[zero_counts > 0]
## PCTBACHMOR NBELPOV100  PCTVACANT PCTSINGLES 
##        143         33        163        306
data <- data %>%
  mutate(
    LNMEDHVAL = log(MEDHVAL),
    LNPCTBACHMOR = log(1+PCTBACHMOR),
    LNNBELPOV100 = log(1+NBELPOV100),
    LNPCTVACANT = log(1+PCTVACANT),
    LNPCTSINGLES = log(1+PCTSINGLES)
  )
longer_version<- data %>%
  pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer_version,aes(x = Value)) +
  geom_histogram(aes(y = ..count..), fill = "black", alpha = 0.7) +  
  facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
    "MEDHVAL" = "Median House Value",
    "PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
    "NBELPOV100" = "# Households Living in Poverty",
    "PCTVACANT" = "% of Vacant Houses",
    "PCTSINGLES" = "% of Single House Units"
  ))) +  
  labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

# histograms of the transformed variables
longer_version2 <- data %>%
  pivot_longer(cols = c(LNMEDHVAL, LNPCTBACHMOR ,LNNBELPOV100,LNPCTVACANT, LNPCTSINGLES),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer_version2,aes(x = Value)) +
  geom_histogram(aes(y = ..count..), fill = "red", alpha = 0.7) +  
  facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
    "LNMEDHVAL" = "Log Median House Value",
    "LNPCTBACHMOR" = "Log % with Bachelor’s Degree",
    "LNNBELPOV100" = "Log # Households in Poverty",
    "LNPCTVACANT" = "Log % Vacant Houses",
    "LNPCTSINGLES" = "Log % Single House Units"
  ))) +  
  labs(x = "Value", y = "Count", title = "Histograms of Dependent and log transformed Predictor Variables") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

ggplot(shape) +
  geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
  scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"), 
                       name = "LNMEDHVAL", 
                       na.value = "transparent") + 
  theme(legend.text = element_text(size = 9),
        legend.title = element_text(size = 10),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        plot.subtitle = element_text(size = 9, face = "italic"),
        plot.title = element_text(size = 12, face = "bold"),
        panel.background = element_blank(),
        panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
  labs(title = "Log Transformed Median House Value")

shpe_longer<- shape %>%
  pivot_longer(cols = c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV"),
               names_to = "Variable",
               values_to = "Value")
custom_titles <- c(
  PCTVACANT   = "Percent of Vacant Houses",
  PCTSINGLES  = "Percent of Single House Units",
  PCTBACHMOR  = "Percent of Bachelor's Degree or Higher",
  LNNBELPOV   = "Logged Transformed Poverty Rate"
)



plot_list <- lapply(unique(shpe_longer$Variable), function(var_name) {
  data_subset <- subset(shpe_longer, Variable == var_name)
  
  ggplot(data_subset) +
    geom_sf(aes(fill = Value), color = "transparent") +
    scale_fill_gradientn(
      colors = c("#fff0f3", "#a4133c"),
      name = var_name,
      na.value = "transparent"
    ) +
    labs(title = custom_titles[[var_name]]) +
    theme(
      legend.text = element_text(size = 8),
      legend.title = element_text(size = 10),
      legend.key.size = unit(0.3, "cm"),
      axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      axis.text.y = element_blank(),
      axis.ticks.y = element_blank(),
      plot.subtitle = element_text(size = 9, face = "italic"),
      plot.title = element_text(size = 15, face = "bold"),
      panel.background = element_blank(),
      panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)
    )
})

# Combine the plots into a grid (2 columns by 2 rows)
combined_plot <- (plot_list[[1]] + plot_list[[2]]) /
                 (plot_list[[3]] + plot_list[[4]])

combined_plot

fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
## 
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + 
##     LNNBELPOV100, data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.25825 -0.20391  0.03822  0.21744  2.24347 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  11.1137661  0.0465330 238.836  < 2e-16 ***
## PCTVACANT    -0.0191569  0.0009779 -19.590  < 2e-16 ***
## PCTSINGLES    0.0029769  0.0007032   4.234 2.42e-05 ***
## PCTBACHMOR    0.0209098  0.0005432  38.494  < 2e-16 ***
## LNNBELPOV100 -0.0789054  0.0084569  -9.330  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared:  0.6623, Adjusted R-squared:  0.6615 
## F-statistic: 840.9 on 4 and 1715 DF,  p-value: < 2.2e-16
anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
## 
## Response: LNMEDHVAL
##                Df  Sum Sq Mean Sq  F value    Pr(>F)    
## PCTVACANT       1 180.392 180.392 1343.087 < 2.2e-16 ***
## PCTSINGLES      1  24.543  24.543  182.734 < 2.2e-16 ***
## PCTBACHMOR      1 235.118 235.118 1750.551 < 2.2e-16 ***
## LNNBELPOV100    1  11.692  11.692   87.054 < 2.2e-16 ***
## Residuals    1715 230.344   0.134                       
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
fitted_values <- fitted(fit)
residuals_values <- residuals(fit)
standardized_residuals <- rstandard(fit)

data <- data %>%
  mutate(
    Fitted = fitted_values,
    Residuals = residuals_values,
    Standardized_Residuals = standardized_residuals)
ggplot(data, aes(x = Fitted, y = Standardized_Residuals)) +
  geom_point(color = "black") +    
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +  
  labs(
    title = "Scatter Plot of Standardized Residuals vs Fitted Values",
    x = "Predicted Values",
    y = "Standardized Residuals"
  ) +
  theme_minimal() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

ggplot(data, aes(x = Standardized_Residuals)) +
  geom_histogram(bins = 30, fill = "black") +
  labs(title = "Histogram of Standardized Residuals", 
       x = "Standardized Residuals", 
       y = "Frequency") +
  theme_minimal() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

longer<-data %>%
  pivot_longer(cols = c("PCTBACHMOR", "LNNBELPOV100", "PCTVACANT", "PCTSINGLES"),
               names_to = "Variable",
               values_to = "Value")

ggplot(longer,aes(x = Value, y = LNMEDHVAL)) +
  geom_point(color = "black") +
  geom_smooth(method = "lm", color = "red", se = FALSE) + 
  facet_wrap(~ Variable, scales = "free", labeller = as_labeller(c(
    "PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
    "LNNBELPOV100" = "Logged Households Living in Poverty",
    "PCTVACANT" = "% of Vacant Houses",
    "PCTSINGLES" = "% of Single House Units"
  )))  +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8)) +
  labs(title = "Scatter Plots of Dependent Variable vs. Predictors", 
       x = "Predictor Value", 
       y = "Log of Median House Value")

custom_labels <- c(
  "% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
  "% of Vacant Houses" = "PCTVACANT",
  "% of Single House Units" = "PCTSINGLES",
  "# Households Living in Poverty" = "LNNBELPOV100"
)

predictor_vars <- data[, c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV100")]

cor_matrix <- cor(predictor_vars, use = "complete.obs", method = "pearson")
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)


ggcorrplot(cor_matrix, 
           method = "square",   
           type = "lower",      
           lab = TRUE,       
           lab_size = 3,      
           colors = c("#d73027", "white", "#1a9850"))+
    labs(title = "Correlation Matrix for all Predictor Variables") +
    theme(plot.subtitle = element_text(size = 9, face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x = element_text(size = 7),
        axis.text.y = element_text(size = 7), 
        axis.title = element_text(size = 8))

LS0tCnRpdGxlOiAnVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikgCmxpYnJhcnkoZ3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9IEZBTFNFfQojIExvYWQgdGhlIGRhdGEKZGF0YSA8LSByZWFkLmNzdigiZGF0YS9SZWdyZXNzaW9uRGF0YS5jc3YiKQpzaGFwZSA8LSBzdF9yZWFkKCJkYXRhL1JlZ3Jlc3Npb25EYXRhLnNocCIpCmBgYAoKCmBgYHtyIHN1bW1hcnkgc3RhdHMsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmRlcGVuZGVudF92YXIgPC0gIk1FREhWQUwiCgpwcmVkaWN0b3JzIDwtIGMoIlBDVEJBQ0hNT1IiLCAiTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpCgpzdW1tYXJ5X3N0YXRzIDwtIGRhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpKSkgJT4lCiAgc3VtbWFyaXNlX2FsbChsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICBzZXBhcmF0ZShWYXJpYWJsZSwgaW50byA9IGMoIlZhcmlhYmxlIiwgIlN0YXQiKSwgc2VwID0gIl8iKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU3RhdCwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkKCgoKc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSA8LSByZWNvZGUoc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSwKICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAiUENUQkFDSE1PUiIgPSAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCikKCgoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIG11dGF0ZSgKICAgIE1lYW4gPSByb3VuZChNZWFuLCAyKSwKICAgIFNEID0gcm91bmQoU0QsIDIpCiAgKQoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIGFycmFuZ2UoVmFyaWFibGUgPT0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpwcmVkaWN0b3Jfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlICE9ICJNZWRpYW4gSG91c2UgVmFsdWUiKQpkZXBlbmRlbnRfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlID09ICJNZWRpYW4gSG91c2UgVmFsdWUiKQoKIyBEZXRlcm1pbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcm93cyBmb3IgZWFjaCBncm91cApzdGFydF9wcmVkIDwtIG1pbihwcmVkaWN0b3Jfcm93cykKZW5kX3ByZWQgICA8LSBtYXgocHJlZGljdG9yX3Jvd3MpCnN0YXJ0X2RlcCAgPC0gbWluKGRlcGVuZGVudF9yb3dzKQplbmRfZGVwICAgIDwtIG1heChkZXBlbmRlbnRfcm93cykKCiMgQ3JlYXRlIHRoZSB0YWJsZSB1c2luZyBrYWJsZSBhbmQgYWRkIGV4dHJhIGZvcm1hdHRpbmcKa2FibGUoc3VtbWFyeV9zdGF0cywgY2FwdGlvbiA9ICJTdW1tYXJ5IFN0YXRpc3RpY3MiLCAKICAgICAgYWxpZ24gPSBjKCJsIiwgImwiLCAibCIpLCBib29rdGFicyA9IFRSVUUsIGVzY2FwZSA9IEZBTFNFICkgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDEsICJTdGF0aXN0aWNzIiA9IDIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgZ3JvdXBfcm93cygiUHJlZGljdG9ycyIsIHN0YXJ0X3ByZWQsIGVuZF9wcmVkKSAlPiUKICBncm91cF9yb3dzKCJEZXBlbmRlbnQgVmFyaWFibGUiLCBzdGFydF9kZXAsIGVuZF9kZXApJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojY2hlY2sgMApjb2x1bW5zX3RvX2NoZWNrIDwtIGMoZGVwZW5kZW50X3ZhciwgcHJlZGljdG9ycykKCnplcm9fY291bnRzIDwtIHNhcHBseShkYXRhW2NvbHVtbnNfdG9fY2hlY2tdLCBmdW5jdGlvbih4KSBzdW0oeCA9PSAwLCBuYS5ybSA9IFRSVUUpKQoKemVyb19jb3VudHNbemVyb19jb3VudHMgPiAwXQoKYGBgCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGxvZygxK1BDVEJBQ0hNT1IpLAogICAgTE5OQkVMUE9WMTAwID0gbG9nKDErTkJFTFBPVjEwMCksCiAgICBMTlBDVFZBQ0FOVCA9IGxvZygxK1BDVFZBQ0FOVCksCiAgICBMTlBDVFNJTkdMRVMgPSBsb2coMStQQ1RTSU5HTEVTKQogICkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbG9uZ2VyX3ZlcnNpb248LSBkYXRhICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiTUVESFZBTCIsICJQQ1RCQUNITU9SIiwgIk5CRUxQT1YxMDAiLCAiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKQoKZ2dwbG90KGxvbmdlcl92ZXJzaW9uLGFlcyh4ID0gVmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBmaWxsID0gImJsYWNrIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJQQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJOQkVMUE9WMTAwIiA9ICIjIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiLAogICAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAgICJQQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBQcmVkaWN0b3IgVmFyaWFibGVzIikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBoaXN0b2dyYW1zIG9mIHRoZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZXMKbG9uZ2VyX3ZlcnNpb24yIDwtIGRhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKExOTUVESFZBTCwgTE5QQ1RCQUNITU9SICxMTk5CRUxQT1YxMDAsTE5QQ1RWQUNBTlQsIExOUENUU0lOR0xFUyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbjIsYWVzKHggPSBWYWx1ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTE5NRURIVkFMIiA9ICJMb2cgTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJMTlBDVEJBQ0hNT1IiID0gIkxvZyAlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZSIsCiAgICAiTE5OQkVMUE9WMTAwIiA9ICJMb2cgIyBIb3VzZWhvbGRzIGluIFBvdmVydHkiLAogICAgIkxOUENUVkFDQU5UIiA9ICJMb2cgJSBWYWNhbnQgSG91c2VzIiwKICAgICJMTlBDVFNJTkdMRVMiID0gIkxvZyAlIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBsb2cgdHJhbnNmb3JtZWQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgoKCgpgYGB7cixmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmdncGxvdChzaGFwZSkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBMTk1FREhWQUwpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjZmZmMGYzIiwgIiNhNDEzM2MiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJMTk1FREhWQUwiLCAKICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIpICsgCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXkiLCBmaWxsID0gTkEsIHNpemUgPSAwLjgpKSArCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlIikKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2hwZV9sb25nZXI8LSBzaGFwZSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiwgIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKY3VzdG9tX3RpdGxlcyA8LSBjKAogIFBDVFZBQ0FOVCAgID0gIlBlcmNlbnQgb2YgVmFjYW50IEhvdXNlcyIsCiAgUENUU0lOR0xFUyAgPSAiUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMiLAogIFBDVEJBQ0hNT1IgID0gIlBlcmNlbnQgb2YgQmFjaGVsb3IncyBEZWdyZWUgb3IgSGlnaGVyIiwKICBMTk5CRUxQT1YgICA9ICJMb2dnZWQgVHJhbnNmb3JtZWQgUG92ZXJ0eSBSYXRlIgopCgoKCnBsb3RfbGlzdCA8LSBsYXBwbHkodW5pcXVlKHNocGVfbG9uZ2VyJFZhcmlhYmxlKSwgZnVuY3Rpb24odmFyX25hbWUpIHsKICBkYXRhX3N1YnNldCA8LSBzdWJzZXQoc2hwZV9sb25nZXIsIFZhcmlhYmxlID09IHZhcl9uYW1lKQogIAogIGdncGxvdChkYXRhX3N1YnNldCkgKwogICAgZ2VvbV9zZihhZXMoZmlsbCA9IFZhbHVlKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICAgY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksCiAgICAgIG5hbWUgPSB2YXJfbmFtZSwKICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiCiAgICApICsKICAgIGxhYnModGl0bGUgPSBjdXN0b21fdGl0bGVzW1t2YXJfbmFtZV1dKSArCiAgICB0aGVtZSgKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjMsICJjbSIpLAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkKICAgICkKfSkKCiMgQ29tYmluZSB0aGUgcGxvdHMgaW50byBhIGdyaWQgKDIgY29sdW1ucyBieSAyIHJvd3MpCmNvbWJpbmVkX3Bsb3QgPC0gKHBsb3RfbGlzdFtbMV1dICsgcGxvdF9saXN0W1syXV0pIC8KICAgICAgICAgICAgICAgICAocGxvdF9saXN0W1szXV0gKyBwbG90X2xpc3RbWzRdXSkKCmNvbWJpbmVkX3Bsb3QKYGBgCgoKYGBge3IgcmVncmVzc2lvbn0KZml0IDwtIGxtKExOTUVESFZBTCB+IFBDVFZBQ0FOVCArIFBDVFNJTkdMRVMgKyBQQ1RCQUNITU9SICsgTE5OQkVMUE9WMTAwLCBkYXRhPWRhdGEpCnN1bW1hcnkoZml0KQpgYGAKYGBge3J9CmFub3ZhX3RhYmxlIDwtIGFub3ZhKGZpdCkKYW5vdmFfdGFibGUKYGBgCmBgYHtyfQpmaXR0ZWRfdmFsdWVzIDwtIGZpdHRlZChmaXQpCnJlc2lkdWFsc192YWx1ZXMgPC0gcmVzaWR1YWxzKGZpdCkKc3RhbmRhcmRpemVkX3Jlc2lkdWFscyA8LSByc3RhbmRhcmQoZml0KQoKZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIEZpdHRlZCA9IGZpdHRlZF92YWx1ZXMsCiAgICBSZXNpZHVhbHMgPSByZXNpZHVhbHNfdmFsdWVzLAogICAgU3RhbmRhcmRpemVkX1Jlc2lkdWFscyA9IHN0YW5kYXJkaXplZF9yZXNpZHVhbHMpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhLCBhZXMoeCA9IEZpdHRlZCwgeSA9IFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIpICsgICAgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKyAgCiAgbGFicygKICAgIHRpdGxlID0gIlNjYXR0ZXIgUGxvdCBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIHZzIEZpdHRlZCBWYWx1ZXMiLAogICAgeCA9ICJQcmVkaWN0ZWQgVmFsdWVzIiwKICAgIHkgPSAiU3RhbmRhcmRpemVkIFJlc2lkdWFscyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIiwgCiAgICAgICB4ID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKCgoKCgoKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxvbmdlcjwtZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXIsYWVzKHggPSBWYWx1ZSwgeSA9IExOTUVESFZBTCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIsIHNlID0gRkFMU0UpICsgCiAgZmFjZXRfd3JhcCh+IFZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJQQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJMTk5CRUxQT1YxMDAiID0gIkxvZ2dlZCBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAgICJQQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCiAgKSkpICArCiAgdGhlbWVfbGlnaHQoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpICsKICBsYWJzKHRpdGxlID0gIlNjYXR0ZXIgUGxvdHMgb2YgRGVwZW5kZW50IFZhcmlhYmxlIHZzLiBQcmVkaWN0b3JzIiwgCiAgICAgICB4ID0gIlByZWRpY3RvciBWYWx1ZSIsIAogICAgICAgeSA9ICJMb2cgb2YgTWVkaWFuIEhvdXNlIFZhbHVlIikKYGBgCgoKCgoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKY3VzdG9tX2xhYmVscyA8LSBjKAogICIlIG9mIEluZGl2aWR1YWxzIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiA9ICJQQ1RCQUNITU9SIiwKICAiJSBvZiBWYWNhbnQgSG91c2VzIiA9ICJQQ1RWQUNBTlQiLAogICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIgPSAiUENUU0lOR0xFUyIsCiAgIiMgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSIgPSAiTE5OQkVMUE9WMTAwIgopCgpwcmVkaWN0b3JfdmFycyA8LSBkYXRhWywgYygiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiLCAiUENUQkFDSE1PUiIsICJMTk5CRUxQT1YxMDAiKV0KCmNvcl9tYXRyaXggPC0gY29yKHByZWRpY3Rvcl92YXJzLCB1c2UgPSAiY29tcGxldGUub2JzIiwgbWV0aG9kID0gInBlYXJzb24iKQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKCmdnY29ycnBsb3QoY29yX21hdHJpeCwgCiAgICAgICAgICAgbWV0aG9kID0gInNxdWFyZSIsICAgCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsICAgICAgCiAgICAgICAgICAgbGFiID0gVFJVRSwgICAgICAgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAgICAgIAogICAgICAgICAgIGNvbG9ycyA9IGMoIiNkNzMwMjciLCAid2hpdGUiLCAiIzFhOTg1MCIpKSsKICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICAgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLCAKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgoKCg==